﻿//========================================================= 
/**@file H002MagDevAdapter.h
 * @brief H002磁条部分指令集
 * 
 * @date 2016-10-03   11:51:03
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_H002MAGDEVADAPTER_H_
#define _LIBZHOUYB_H002MAGDEVADAPTER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"
#include "../../device/magnetic/MagneticDevAdapter.h"
using zhou_yb::device::magnetic::MagneticDevAdapter;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace magnetic {
//--------------------------------------------------------- 
/// H002磁条部分标准指令集
class H002MagDevAdapter :
    public DevAdapterBehavior<IInteractiveTrans>,
    public InterruptBehavior,
    public TimeoutBehavior,
    public RefObject
{
protected:
    //----------------------------------------------------- 
    /// 等待读取磁条数据
    bool _WaitMagCard(ByteBuilder* pTr1, ByteBuilder* pTr2, ByteBuilder* pTr3)
    {
        LOGGER(_log << "超时时间:<" << _waitTimeout << "ms>\n"
            << "轮询间隔:<" << _waitInterval << "ms>\n");

        Timer timer;
        ByteBuilder buff(256);
        DeviceError::ErrorCode errCode = DeviceError::UnKnownErr;
        bool bRead = false;
        while(timer.Elapsed() < _waitTimeout)
        {
            if(InterruptBehavior::Implement(*this))
            {
                ResetErr();
                _logErr(DeviceError::OperatorInterruptErr);
                return false;
            }

            buff.Clear();
            errCode = IsMagPresent(_pDev, buff);
            if(errCode == DeviceError::DevIsBusyErr)
            {
                Timer::Wait(_waitInterval);
            }
            else if(DeviceError::IsSuccess(errCode))
            {
                bRead = true;
                break;
            }
            else
            {
                _logErr(errCode);
                return false;
            }
        }
        ASSERT_FuncErrInfo(bRead, DeviceError::WaitTimeOutErr, "等待刷磁超时");
        MagneticDevAdapter::MagneticMode mode = MagneticDevAdapter::UnpackRecvCmd(buff, pTr1, pTr2, pTr3);
        if(mode == MagneticDevAdapter::UnKnownMode)
        {
            _logErr(DeviceError::RecvFormatErr, "磁条数据格式不正确");
            return false;
        }
        return true;
    }
    //----------------------------------------------------- 
public:
    //----------------------------------------------------- 
    /**
     * @brief 检测磁条是否为刷卡状态
     * @date 2016-09-17 10:11
     * 
     * @param [in] dev 
     * @param [in] trBuff 
     * 
     * @return DeviceError::ErrorCode 操作过程中的错误码
     * @retval DeviceError::DevIsBusyErr 标识仍然在等待刷磁
     */
    static DeviceError::ErrorCode IsMagPresent(IInteractiveTrans& dev, ByteBuilder& trBuff)
    {
        byte magCmd[2] = { 0x1B, 'j' };
        ByteBuilder buff(256);
        bool bRead = false;

        if(!dev.Write(ByteArray(magCmd, 2)))
            return DeviceError::SendErr;
        
        while(buff.GetLength() < 2)
        {
            if(!dev.Read(buff))
                return DeviceError::RecvErr;
        }
        // 有磁条数据
        if(buff[0] == 0x1B)
        {
            switch(buff[1])
            {
            // 没有刷磁
            case 0x30:
                return DeviceError::DevIsBusyErr;
            // 已刷磁,有状态码格式
            case 0x31:
                buff.RemoveFront(2);
                bRead = true;
                break;
            // 已刷磁,无状态码格式
            case 0x73:
                bRead = true;
                break;
            }
        }
        bRead = MagneticDevAdapter::RecvByFormat(dev, buff);
        if(!bRead)
            return DeviceError::RecvFormatErr;
        trBuff += buff;
        return DeviceError::Success;
    }
    //----------------------------------------------------- 
    /// 等待读取磁条明文数据
    bool WaitMagCard(ByteBuilder* pTr1, ByteBuilder* pTr2, ByteBuilder* pTr3)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        return _logRetValue(_WaitMagCard(pTr1, pTr2, pTr3));
    }
    /// 等待读取磁条密文数据
    bool WaitEncryptMagCard(ByteBuilder* pTr1, ByteBuilder* pTr2, ByteBuilder* pTr3)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();

        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);

        ASSERT_FuncRet(_WaitMagCard(&tr1, &tr2, &tr3));

        if(pTr1 != NULL)
            ByteConvert::Fold(tr1, *pTr1);
        if(pTr2 != NULL)
            ByteConvert::Fold(tr2, *pTr2);
        if(pTr3 != NULL)
            ByteConvert::Fold(tr3, *pTr3);
        LOGGER(_log << "一磁道数据:<";_log.WriteStream(tr1) << ">\n";
        _log << "二磁道数据:<";_log.WriteStream(tr2) << ">\n";
        _log << "三磁道数据:<";_log.WriteStream(tr3) << ">\n");

        return _logRetValue(true);
    }
    /**
     * @brief 开始明文读取磁条
     * @date 2016-07-14 15:38
     */
    bool MagRead()
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte magCmd[2] = { 0x1B, 0x5D };
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(magCmd, 2)), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /**
     * @brief 清除磁条状态
     * @date 2017-07-29 17:00
     */
    bool MagClear()
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte magCmd[] = { 0x1B, 0x30 };
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(magCmd, 2)), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /**
     * @brief 开始密文读取磁条
     * @date 2016-07-14 15:38
     * 
     * @param [in] mkIndex 加密的主密钥索引
     * @param [in] wkIndex 加密的工作密钥索引
     */
    bool MagEncryptRead(byte mkIndex, byte wkIndex)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "超时时间:<" << _waitTimeout << "ms>\n"
            << "轮询间隔:<" << _waitInterval << "ms>\n";
        _log << "主密钥索引:<" << _hex(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex(wkIndex) << ">\n");
        ASSERT_Device();
        byte magCmd[2] = { 0x1B, 0x5C };

        ByteBuilder sCmd(16);
        sCmd += ByteArray(magCmd, 2);
        sCmd += mkIndex;
        sCmd += wkIndex;

        ASSERT_FuncErrRet(_pDev->Write(sCmd), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /**
     * @brief 返回磁条是否为H002轮询方式
     * @date 2017-05-10 23:11
     * 
     * @param [out] isPolling 返回磁条是否为H002轮询的模式
     */
    bool IsPollingMode(bool& isPolling)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();

        byte cmd[] = { 0x1B, 0x6A };
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(cmd, 2)), DeviceError::SendErr);

        ByteBuilder rCmd(8);
        ASSERT_FuncErrRet(_pDev->Read(rCmd), DeviceError::RecvErr);
        ASSERT_FuncErrRet(rCmd.GetLength() > 0 && rCmd[0] == 0x1B, DeviceError::RecvFormatErr);
        
        isPolling = (rCmd[1] == 0x30 || rCmd[0] == 0x31);
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
};
//--------------------------------------------------------- 
} // namespace magnetic
} // namespace application 
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_H002MAGDEVADAPTER_H_
//========================================================= 